package com.stone.design.mode.chain;

import java.util.stream.Stream;

/**
 * 退款校验链
 * RefundForBaseDTO：参数传递
 * RefundTransferDTO：可以作为具体判断的type
 *
 * @author Mr_wenpan@163.com
 */
public abstract class ValidatorHandler<T extends RefundForBaseDTO, R extends RefundTransferDTO> {

    /**
     * 下一个处理器节点
     */
    public ValidatorHandler<T, R> nextHandler;

    public void setNextHandler(ValidatorHandler<T, R> nextHandler) {
        this.nextHandler = nextHandler;
    }

    /**
     * 过滤链，这里使用模板方法设计模式，将每个节点公用的过滤方法抽取到父类
     *
     * @param t    入参
     * @param r    参数传递
     * @param type 退款类型
     */
    public void filter(T t, R r, String type) {
        // 找到当前节点匹配的条件（类型），如果找到了则执行当前节点的 validate 方法
        if (supports().anyMatch(s -> s.equals(type))) {
            validate(t, r);
        }
        // 执行到最后一个节点后开始返回
        if (nextHandler == null) {
            return;
        }
        // 继续执行下一个节点的过滤方法
        nextHandler.filter(t, r, type);
    }

    /**
     * 具体校验逻辑
     *
     * @param t 入参
     * @param r 参数传递
     */
    protected abstract void validate(T t, R r);

    /**
     * 支持的退款类型，即该节点满足这里返回的条件之一即可执行该节点的 validate 方法
     * 这里返回的是一个数组的Stream
     *
     * @see RefundTypeEnum
     */
    protected abstract Stream<String> supports();

    /**
     * 校验器的执行顺序
     *
     * @return 执行顺序
     */
    protected abstract int getOrder();
}